#include "general.h"

#include <buolabase_basicio.h>
#include <cfile.h>

std::unordered_map<std::string,CFolderData*> CFolderData::mAll;

CFolderData::CFolderData(const CURL &pURL)
    : mFolder(pURL)
{
    Load();
}

CFolderData::~CFolderData()
{
    Save();
    mAll.erase(mFolder.GetURL());
}

void CFolderData::Load()
{
    if(mDataFileName.empty())
    {
        mDataFileName=CMetaDataIndex::GetIndex()->
                        GetFilenameFor(mFolder.GetURL(),false);
        if(mDataFileName.empty()) return;
    }

    PFile lFile=CFile::Get(CURL::GetHome()+".buola/metadata"+mDataFileName);
    COldBuolaStream *lStream=lFile->GetStream(io::EMode::READ);

    //first own address
    std::string lOwnName;
    lStream->ReadStr(lOwnName);
    //then number of files
    int lFileCount;
    lStream->ReadNum(&lFileCount,4);
    //and the files
    for(int i=0;i<lFileCount;i++)
    {
        //first the name
        std::wstring lName;
        lStream->ReadStr(lName);

        CFileData *lFileData=new CFileData;
        mFiles[utf8(lName)]=lFileData;

        //then the contents
        lFileData->Read(lStream);
    }
}

void CFolderData::Save()
{
    if(mDataFileName.empty())
    {
        mDataFileName=CMetaDataIndex::GetIndex()->
                        GetFilenameFor(mFolder.GetURL(),true);
    }

    PFile lFile=CFile::Get(CURL::GetHome()+".buola/metadata"+mDataFileName);
    COldBuolaStream *lStream=lFile->GetStream(io::EMode::TRUNCATE);

    //first own address
    lStream->WriteStr(mFolder.GetURL());
    //then number of files
    lStream->WriteNum(mFiles.size(),4);

    //and the files
    for(std::unordered_map<std::string,CFileData*>::iterator i=mFiles.begin();
                        i!=mFiles.end();++i)
    {
        //first the name
        lStream->WriteStr(i->first);
        //then the contents
        i->second->Write(lStream);
    }

    delete lStream;
}

void CFolderData::GetValue(const std::string &pName,const std::string &pKey,
                            UValue &pValue)
{
    CFileData *lFileData=GetFileData(pName,false);

    if(lFileData)
    {
        lFileData->GetValue(pKey,pValue);
    }
}

void CFolderData::SetValue(const std::string &pName,const std::string &pKey,
                    const UValue &pValue)
{
    CFileData *lFileData=GetFileData(pName,true);

    lFileData->SetValue(pKey,pValue);
}

CFileData *CFolderData::GetFileData(const std::string &pName,bool pCreate)
{
    CFileData *lFileData=mFiles[pName];

    if(!lFileData&&pCreate)
    {
        lFileData=new CFileData;
        mFiles[pName]=lFileData;
    }
    return lFileData;
}

PFolderData CFolderData::GetFolder(const CURL &pURL)
{
    std::string lURL(pURL.GetURL());

    CFolderData *lRet=mAll[lURL];

    if(!lRet)
    {
        lRet=new CFolderData(pURL);
        mAll[lURL]=lRet;
    }

    return lRet;
}
